#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include "../src/utils/logger.h"
#include "../src/utils/perf_monitor.h"

void test_logger_functionality() {
    printf("Testing logger functionality...\n");
    
    // Create logger configuration
    logger_config_t config = logger_default_config();
    strcpy(config.log_file_path, "test_gudb.log");
    config.enable_console_output = true;
    
    // Create and initialize logger
    logger_t* logger = logger_create(&config);
    assert(logger != NULL);
    
    int result = logger_init(logger);
    assert(result == 0);
    
    // Test logging at different levels
    LOG_DEBUG("TEST", "This is a debug message");
    LOG_INFO("TEST", "This is an info message");
    LOG_WARN("TEST", "This is a warning message");
    LOG_ERROR("TEST", "This is an error message");
    
    // Test query logging
    LOG_QUERY("SELECT * FROM users WHERE id = 1", 150, 1, NULL);
    LOG_QUERY("SELECT COUNT(*) FROM orders", 2500, 1, "Table not found");
    LOG_SLOW_QUERY("SELECT * FROM products JOIN categories", 1500, 100);
    
    // Test authentication logging
    LOG_AUTH_EVENT("admin", "LOGIN", true);
    LOG_AUTH_EVENT("guest", "LOGIN", false);
    
    // Test performance logging
    LOG_PERFORMANCE("query_time", 125.5, "ms");
    LOG_PERFORMANCE("cache_hit_ratio", 85.2, "%");
    
    // Get logger statistics
    logger_stats_t stats;
    result = logger_get_stats(logger, &stats);
    assert(result == 0);
    
    printf("Logger stats: total_entries=%llu, file_size=%llu bytes\n", 
           stats.total_entries, stats.current_file_size);
    
    // Cleanup
    logger_destroy(logger);
    printf("Logger test completed successfully!\n\n");
}

void test_perf_monitor_functionality() {
    printf("Testing performance monitor functionality...\n");
    
    // Create logger first
    logger_config_t logger_config = logger_default_config();
    strcpy(logger_config.log_file_path, "test_perf.log");
    logger_config.enable_console_output = true;
    
    logger_t* logger = logger_create(&logger_config);
    assert(logger != NULL);
    logger_init(logger);
    logger_set_global(logger);
    
    // Create performance monitor configuration
    perf_monitor_config_t config = perf_monitor_default_config();
    config.slow_query_threshold_ms = 100;  // 100ms threshold for testing
    
    // Create and initialize performance monitor
    perf_monitor_t* monitor = perf_monitor_create(&config);
    assert(monitor != NULL);
    
    int result = perf_monitor_init(monitor, logger, NULL);
    assert(result == 0);
    
    perf_monitor_set_global(monitor);
    
    // Test query monitoring
    printf("Testing query execution monitoring...\n");
    
    // Test fast query
    query_execution_context_t* ctx1 = perf_monitor_start_query(
        monitor, "SELECT * FROM users LIMIT 10", "admin", "testdb");
    assert(ctx1 != NULL);
    
    usleep(50000); // Sleep 50ms - should be fast
    
    perf_monitor_end_query(monitor, ctx1, 100, 10, 1024, NULL);
    perf_monitor_free_query_context(ctx1);
    
    // Test slow query
    query_execution_context_t* ctx2 = perf_monitor_start_query(
        monitor, "SELECT * FROM orders JOIN customers", "user1", "testdb");
    assert(ctx2 != NULL);
    
    usleep(150000); // Sleep 150ms - should be slow
    
    perf_monitor_end_query(monitor, ctx2, 10000, 500, 50000, NULL);
    perf_monitor_free_query_context(ctx2);
    
    // Test failed query
    query_execution_context_t* ctx3 = perf_monitor_start_query(
        monitor, "SELECT * FROM invalid_table", "user2", "testdb");
    assert(ctx3 != NULL);
    
    usleep(10000); // Sleep 10ms
    
    perf_monitor_end_query(monitor, ctx3, 0, 0, 0, "Table 'invalid_table' doesn't exist");
    perf_monitor_free_query_context(ctx3);
    
    // Test system metrics
    printf("Testing system metrics collection...\n");
    
    perf_monitor_connection_opened(monitor);
    perf_monitor_connection_opened(monitor);
    perf_monitor_connection_closed(monitor);
    
    perf_monitor_cache_hit(monitor);
    perf_monitor_cache_hit(monitor);
    perf_monitor_cache_miss(monitor);
    
    perf_monitor_disk_read(monitor, 4096);
    perf_monitor_disk_write(monitor, 2048);
    
    perf_monitor_update_memory_usage(monitor, 128);
    
    // Update and get metrics
    result = perf_monitor_update_metrics(monitor);
    assert(result == 0);
    
    system_performance_metrics_t metrics;
    result = perf_monitor_get_metrics(monitor, &metrics);
    assert(result == 0);
    
    printf("Performance metrics:\n");
    printf("  Total queries: %llu\n", metrics.total_queries_count);
    printf("  Slow queries: %llu\n", metrics.slow_queries_count);
    printf("  Failed queries: %llu\n", metrics.failed_queries_count);
    printf("  QPS: %llu\n", metrics.queries_per_second);
    printf("  Avg query time: %.2f ms\n", metrics.avg_query_time_ms);
    printf("  Max query time: %.2f ms\n", metrics.max_query_time_ms);
    printf("  Active connections: %llu\n", metrics.active_connections);
    printf("  Cache hit ratio: %llu%%\n", metrics.cache_hit_ratio_percent);
    printf("  Memory usage: %llu MB\n", metrics.memory_usage_mb);
    
    // Test logging functions
    perf_monitor_log_system_status(monitor);
    perf_monitor_log_slow_query_summary(monitor);
    
    // Test macro functions
    printf("Testing convenience macros...\n");
    
    query_execution_context_t* ctx4 = PERF_START_QUERY("SELECT 1", "macro_user", "testdb");
    usleep(25000);
    PERF_END_QUERY(ctx4, 1, 1, 10, NULL);
    perf_monitor_free_query_context(ctx4);
    
    PERF_CONNECTION_OPENED();
    PERF_CONNECTION_CLOSED();
    PERF_CACHE_HIT();
    PERF_CACHE_MISS();
    PERF_DISK_READ(1024);
    PERF_DISK_WRITE(512);
    
    // Cleanup
    perf_monitor_destroy(monitor);
    logger_destroy(logger);
    
    printf("Performance monitor test completed successfully!\n\n");
}

void test_slow_query_detection() {
    printf("Testing slow query detection...\n");
    
    // Create minimal setup
    logger_config_t logger_config = logger_default_config();
    strcpy(logger_config.log_file_path, "test_slow.log");
    logger_config.enable_console_output = false;
    
    logger_t* logger = logger_create(&logger_config);
    logger_init(logger);
    
    perf_monitor_config_t config = perf_monitor_default_config();
    config.slow_query_threshold_ms = 50;  // 50ms threshold
    
    perf_monitor_t* monitor = perf_monitor_create(&config);
    perf_monitor_init(monitor, logger, NULL);
    
    // Test various execution times
    assert(perf_monitor_is_slow_query(monitor, 25) == false);  // Fast
    assert(perf_monitor_is_slow_query(monitor, 50) == true);   // At threshold
    assert(perf_monitor_is_slow_query(monitor, 100) == true);  // Slow
    
    printf("Slow query detection working correctly!\n");
    
    // Cleanup
    perf_monitor_destroy(monitor);
    logger_destroy(logger);
}

void test_log_rotation() {
    printf("Testing log rotation...\n");
    
    // Create logger with small max file size for testing
    logger_config_t config = logger_default_config();
    strcpy(config.log_file_path, "test_rotation.log");
    config.max_file_size = 1024;  // 1KB for testing
    config.enable_console_output = false;
    
    logger_t* logger = logger_create(&config);
    logger_init(logger);
    
    // Write many log entries to trigger rotation
    for (int i = 0; i < 50; i++) {
        logger_log(logger, LOG_LEVEL_INFO, "ROTATION_TEST", 
                   "This is test log entry number %d with some additional text to make it longer", i);
    }
    
    printf("Log rotation test completed!\n");
    
    logger_destroy(logger);
}

int main() {
    printf("=== GuDB Performance Monitoring System Test ===\n\n");
    
    test_logger_functionality();
    test_perf_monitor_functionality();
    test_slow_query_detection();
    test_log_rotation();
    
    printf("=== All tests completed successfully! ===\n");
    printf("Check the generated log files:\n");
    printf("  - test_gudb.log (general logging test)\n");
    printf("  - test_perf.log (performance monitoring test)\n");
    printf("  - test_slow.log (slow query detection test)\n");
    printf("  - test_rotation.log* (log rotation test)\n");
    
    return 0;
}